package com.xcity.game.formation;

import java.text.MessageFormat;

import com.xcity.db.entity.Employee;
import com.xcity.db.entity.Employee.State;
import com.xcity.db.entity.Player;
import com.xcity.game.combat.CombatException;
import com.xcity.game.common.MessageConst;

public class Formation {

	protected byte type;
	protected long[] employeeIds;
	protected Employee[] employees; // cache
	
	protected Player owner;
//	protected boolean uninitialized;
	
	public static final byte TYPE_NORMAL = 0; // 普通战斗阵型
	public static final byte TYPE_ARENA_DEFENSE = 1; // 竞技场防守阵型
	public static final byte TYPE_PEAK_ROAD = 2; // 爬塔（巅峰之路）使用阵型
	public static final byte TYPE_MINE_DEFENSE = 3;//矿防守阵型
	
	public static final int FORMATION_CAPCITY = 4;
	public static final long[] EMPTY_FORMATION = new long[FORMATION_CAPCITY];
	
	protected Formation(Player owner, byte type) {
		this(owner, new long[FORMATION_CAPCITY], type);
	}
	
	protected Formation(Player owner, long[] employeeIds, byte type) {
		this.owner = owner;
		this.employeeIds = employeeIds;
		this.type = type;
	}
	
//	private Formation(Player owner, long[] employeeIds, byte type, boolean uninitialized) {
//		this.owner = owner;
//		this.employeeIds = employeeIds;
//		this.type = type;
//		this.uninitialized = uninitialized;
//	}
	
	public void setOwner(Player player) {
		this.owner = player;
	}
	
	public long[] getIds() {
		return employeeIds;
	}
	
	public Employee[] getUnits() {
		if (employees == null) {
			employees = new Employee[employeeIds.length];
			for (int i = employees.length - 1; i >= 0; i--) {
				long id = employeeIds[i];
				if (id != 0L) {
					employees[i] = owner.getEmployees().get(id);
				}
			}
		}
		return employees;
	}
	
	public long[] replace(int pos, Employee employee) throws CombatException {
		Employee[] employees = getUnits();
		if (pos < 0 || pos >= employees.length) {
			throw new CombatException(MessageConst.ILLEGAL_OPERATION);
		}
		long[] employeeIds = this.employeeIds;
		Employee previous = null; // 被下阵的/被替换掉的
		if (employee != null) {
			if (State.IN_FORMATION.enable && employee.getState() != State.FREE && employee.getState() != State.IN_FORMATION) {
				throw new CombatException(MessageConst.FORMATION_EMPLOYEE_STATE_ERROR);
			}
			if (type == TYPE_PEAK_ROAD && owner.getPeakRoadInstance().isDied(employee)) {
				throw new CombatException(MessageConst.COMBAT_UNIT_DIED);
			}
			if (isDuplicated(employees, employee)) {
				throw new CombatException(MessageFormat.format(MessageConst.FORMATION_HAS_THE_SAME_EMPLOYEE, employee.getTemplate().getName()));
			}
			if (type == TYPE_NORMAL && State.IN_FORMATION.enable) {
				employee.setState(State.IN_FORMATION, true);
			}
			previous = employees[pos];
			employees[pos] = employee;
			employeeIds[pos] = employee.getId();
//			uninitialized = false;
		} else {
			previous = employees[pos];
			employees[pos] = null;
			employeeIds[pos] = 0L;
		}
		if (previous != null && type == TYPE_NORMAL && State.IN_FORMATION.enable) {
			previous.setState(State.FREE, true);
		}
		return employeeIds;
	}
	
	public void validate() {
		if (type == TYPE_PEAK_ROAD) {
			Employee[] employees = getUnits();
			long[] employeeIds = getIds();
			for (int i = 0; i < employeeIds.length; i++) {
				// 死亡单位移除阵型
				if (employees[i] != null && owner.getPeakRoadInstance().isDied(employees[i])) {
					employees[i] = null;
					employeeIds[i] = 0L;
				}
			}
		}
	}
	
	public void remove(Employee employee) {
		long[] ids = getIds();
		Employee[] emps = getUnits();
		for (int i = 0; i < ids.length; i++) {
			if (ids[i] == employee.getId()) {
				ids[i] = 0L;
				emps[i] = null;
				break;
			}
		}
	}
	
	public boolean contains(Employee employee) {
		return pos(employee) != -1;
	}
	
	public int pos(Employee employee) {
		long[] ids = getIds();
		for (int i = ids.length - 1; i >= 0; i--) {
			if (ids[i] == employee.getId()) {
				return i;
			}
		}
		return -1;
	}
	
	private static boolean isDuplicated(Employee[] employees, Employee target) {
		for (Employee employee : employees) {
			if (employee != null && employee.getTemplate().getId() == target.getTemplate().getId()) {
				return true;
			}
		}
		return false;
	}
	
	public static boolean isValid(byte type) {
		return type >= TYPE_NORMAL && type <= TYPE_MINE_DEFENSE;
	}
	
}
